<template>
  <div class="my-table-container" v-loading="loading">
    <div :style="{ height: maxSelfHeight + 'px' }">
      <el-auto-resizer>
        <template #default="{ height, width }">
          <el-table-v2
            ref="tableRef"
            :header-class="headerClass"
            :row-class="getRowStyle"
            :columns="tableColumns"
            :data="tableDataList"
            :width="width"
            :height="height"
            :scrollbar-always-on="scrollbarShow"
            :row-key="rowKey"
            :fixed="true"
            @column-sort="onSort"
            v-model:sort-state="sortState"
          >
            <template #header-cell="{ column }">
              <div class="cell">
                {{ column.title }}
              </div>
            </template>
            <template #cell="{ rowData, column }">
              <TruncatedText
                :text="
                  rowData[column.key] === 0 || !!rowData[column.key]
                    ? String(rowData[column.key])
                    : ''
                "
                :width="column.width"
              >
                <span class="table-td cell-content">
                  {{
                    rowData[column.key] === 0 || !!rowData[column.key]
                      ? rowData[column.key]
                      : ""
                  }}
                </span>
              </TruncatedText>
            </template>
            <!-- <template #empty>
              <span class="el-table__empty-text">{{ $t("common.noData") }}</span>
            </template> -->
          </el-table-v2>
        </template>
      </el-auto-resizer>
    </div>
    <!-- 分页处理 start -->
    <template v-if="pagination">
      <div class="page-list">
        <div class="flex-start flex-wrap">
          <div class="page-start flex-center" v-if="selection && showSelectSize">
            <span>{{ $t("common.hasSelect") }}&nbsp;</span>
            <span>{{ selectList.length }}&nbsp;</span>
            <span v-if="locale === 'zh-CN'">{{ $t("common.strip") }}</span>
          </div>
          <div class="page-container">
            <el-pagination
              :small="true"
              :size="size"
              :page-size="pageSize"
              :current-page="pageIndex"
              :page-sizes="pageSizeList"
              :pager-count="pageCount"
              :layout="paginationLayout"
              :total="totalCount"
              @size-change="paginationOperate(1, $event)"
              @current-change="paginationOperate(2, $event)"
            >
            </el-pagination>
          </div>
          <div class="page-end">
            <slot name="end"></slot>
          </div>
        </div>
      </div>
    </template>
    <!-- 分页处理  end  -->
  </div>
</template>

<script lang="tsx">
import type { FunctionalComponent } from "vue";
import type { CheckboxValueType, Column, SortBy } from "element-plus";
import TruncatedText from "@/components/truncatedText/index.vue";
import {
  defineComponent,
  ref,
  unref,
  computed,
  watch,
  reactive,
  nextTick,
  onUnmounted,
  onMounted,
  h,
  watchEffect,
} from "vue";
type SelectionCellProps = {
  value: boolean;
  intermediate?: boolean;
  onChange: (value: CheckboxValueType) => void;
};

const SelectionCell: FunctionalComponent<SelectionCellProps> = ({
  value,
  intermediate = false,
  onChange,
}) => {
  return (
    <ElCheckbox onChange={onChange} modelValue={value} indeterminate={intermediate} />
  );
};
import { ElCheckbox, TableV2SortOrder } from "element-plus";
import moment from "moment";
import { useI18n } from "vue-i18n";
import { useSidebarStore } from "@/store/sidebar";
import { getLanguageInfo } from "@/utils/common";
export default defineComponent({
  name: "NbTable",
  components: { TruncatedText },
  props: {
    // 需要设置行字体颜色的index下标
    errorRowList: {
      type: Array,
      default: () => [],
    },
    size: {
      // 頁面路由
      type: String,
      default: "large",
    },
    tableData: {
      type: Array,
      default: () => [],
    },
    columns: {
      type: Array,
      default: () => [],
    },
    loading: {
      type: Boolean,
      default: false,
    },
    headerClass: {
      type: String,
      default: "nbTable-header",
    },
    // 分页相关 -- START
    height: {
      type: Number,
      default: 550,
    },
    autoHeight: {
      type: Boolean,
      default: true,
    },
    maxHeight: {
      type: Number,
      default: 550,
    },
    pagination: {
      type: Boolean,
      default: true,
    },
    scrollbarShow: {
      type: Boolean,
      default: true,
    },
    pageSize: {
      type: Number,
      default: 10,
    },
    pageIndex: {
      type: Number,
      default: 1,
    },
    pageSizeList: {
      type: Array,
      default: () => [10, 30, 50, 70, 100],
    },
    pageCount: {
      type: Number,
      default: 7,
    },
    paginationLayout: {
      type: String,
      default: "total, sizes, ->, prev, pager, next, jumper",
    },
    totalCount: {
      type: Number,
      default: 0,
    },
    changeSize: {
      type: Function,
      default: () => {},
    },
    changePageIndex: {
      type: Function,
      default: () => {},
    },
    // 分页相关 -- END

    // 多选相关 -- START
    selection: {
      type: Boolean,
      default: false,
    },
    showSelectSize: {
      type: Boolean,
      default: true,
    },
    rowKey: {
      type: String,
      default: "rowKey",
    },
    selectionFixed: {
      type: Boolean,
      default: false,
    },
    handleSelectionChange: {
      type: Function,
      default: () => {},
    },
    // 多选相关 -- END
  },
  setup(props, context) {
    let { autoHeight, maxHeight, pagination } = props;
    let maxSelfHeight = ref(maxHeight);
    let sidebar = useSidebarStore();
    const { t, locale } = useI18n();
    const tableRef = ref(null);
    let selectList = ref([]);
    let tableColumns = ref([]);
    let tableDataList = ref([]);
    let tableScrollY = ref(null);
    const getRowStyle = ({ row, rowIndex }) => {
      let str = "";
      // if (props.errorRowList.includes(rowIndex)) {
      //   str += " error-cell";
      // }
      return str;
    };
    const sortState = ref<SortState>({});
    const getLabel = (item) => {
      //处理表头拼借变量含有value的第一个值
      if (Array.isArray(item)) {
        let flag = item.some((v) => v.hasOwnProperty("value"));
        if (item.length === 1) {
          if (!!item[0].value) {
            return item[0].value;
          } else {
            return t(item[0]);
          }
        } else {
          let arr;
          if (flag) {
            let i = item[0].value;
            arr = item.slice(1).map((v) => t(v));
            let str = getLanguageInfo(locale.value, arr);
            if (locale.value === "en-US") {
              return i + " " + str;
            } else {
              return i + str;
            }
          } else {
            arr = item.map((v) => t(v));
            let str = getLanguageInfo(locale.value, arr);
            return str;
          }
        }
      } else {
        return t(item);
      }
    };
    const initColumns = () => {
      let arr = props.columns.map((v, index) => {
        if (v.sortable) {
          sortState.value[v.prop] = TableV2SortOrder.ASC;
        }
        return {
          ...v,
          align: "center",
          key: v.prop,
          dataKey: v.prop,
          title: getLabel(v.label),
        };
      });
      if (props.selection) {
        arr.unshift({
          key: "selection",
          width: 60,
          fixed: "left",
          cellRenderer: ({ rowData }) => {
            const onChange = (value: CheckboxValueType) => {
              let index = selectList.value.findIndex((v) => v.rowKey === rowData.rowKey);
              if (value) {
                index === -1 && selectList.value.push(rowData);
              } else {
                index > -1 && selectList.value.splice(index, 1);
              }
              rowData.checked = value;
            };
            return (
              <div class="flex-center w-[100%]">
                <SelectionCell value={rowData.checked} onChange={onChange} />
              </div>
            );
          },
          headerCellRenderer: () => {
            const data = tableDataList.value;
            const _data = unref(data);
            const onChange = (value: CheckboxValueType) => {
              data.value = _data.map((row) => {
                row.checked = value;
                return row;
              });
              selectList.value = data.value.filter((v) => v.checked);
              props.handleSelectionChange(selectList.value);
            };
            const allSelected = _data.every((row) => row.checked);
            const containsChecked = _data.some((row) => row.checked);

            return (
              <div class="flex-center w-[100%]">
                <SelectionCell
                  value={allSelected}
                  intermediate={containsChecked && !allSelected}
                  onChange={onChange}
                />
              </div>
            );
          },
        });
      }
      tableColumns.value = arr;
    };
    const setMaxSelfHeight = () => {
      nextTick(() => {
        let container = document.querySelector(".my-table-container");
        let top = 0;
        let rect = container && container.getBoundingClientRect();
        top = rect ? rect.top : 0;
        let pageHeight = document.body.scrollHeight;
        //底部分页36px
        let paginationHeight = pagination ? 36 : 0;
        // 最终高度还需要减去页面布局上的padding，margin等
        maxSelfHeight.value = pageHeight - paginationHeight - top - 20 - 10 * 2;
      });
    };
    const paginationOperate = (type, e) => {
      // 改变index和分页大小，回滚到顶部
      tableRef.value && tableRef.value.scrollTo(0, 0);
      if (type === 1) {
        props.changeSize(e);
      } else {
        props.changePageIndex(e);
      }
      // 清空勾选
      selectList.value = [];
      props.handleSelectionChange(selectList.value);
    };
    const onSort = ({ key, order }: SortBy) => {
      sortState.value[key] = order;
      tableDataList.value = tableDataList.value.reverse();
    };
    watch(
      () => props.tableData,
      (n) => {
        tableDataList.value = n.map((v) => {
          return {
            ...v,
            checked: false,
          };
        });
      },
      { immediate: true }
    );
    onMounted(() => {
      // 将表格最高高度设为占满屏幕
      if (autoHeight) {
        setMaxSelfHeight();
        window.addEventListener("resize", setMaxSelfHeight);
      }
      initColumns();
    });
    onUnmounted(() => {
      if (autoHeight) {
        window.removeEventListener("resize", setMaxSelfHeight);
      }
    });
    return {
      locale,
      selectList,
      tableDataList,
      tableColumns,
      tableRef,
      getRowStyle,
      maxSelfHeight,
      paginationOperate,
      sortState,
      onSort,
    };
  },
});
</script>
<style lang="scss">
.el-table-v2__sort-icon {
  display: block;
}
</style>
<style scoped lang="scss">
.my-table-container {
  width: 100%;
  background-color: #fff;
  padding: 0 0 20px;
  border-radius: 16px;
  position: relative;
  overflow: hidden;
}

.page-list {
  overflow: hidden;
  margin-top: 12px;
  padding: 0 15px;
}

.el-table thead th {
  background: #f7f4ef !important;
}

.el-table .cell,
.el-table th div {
  padding-right: 0 !important;
}

.el-table thead th {
  background: #f7f4ef;
}

.el-table--enable-row-hover .el-table__body tr:hover > td {
  background-color: #f7f4ef;
}

.table-first {
  text-align: center !important;
}

.context-menu {
  position: absolute;
  z-index: 100;
  background: transparent;
  display: flex;
  flex-direction: column;
  gap: 10px;
  div {
    padding: 5px 10px;
    border-radius: 10px;
    min-width: 120px;
    text-align: center;
    cursor: pointer;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}

.page-start {
  margin-right: 16px;
  height: 100%;

  span {
    font-size: 12px;
    color: var(--el-text-color-regular);
    font-weight: normal;
  }
}
.page-container {
  flex: 1;
}
.page-end {
  padding-left: 10px;
}
</style>
